package logic;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import userinterface.UserInt;
import csv.CSVFile;
import csv.CSVParser;
import csv.CSVWriter;
import db.DatabaseManager;

public class MainLogic
{
  private UserInt ui;
  private Map<String, String> barcodeTable;
  private CSVFile persoonTable;
  private CSVFile lidTable;
  private ArrayList<String> partyTable;
  private ArrayList<String> peopleEntered;
  
  private boolean barcodeLoaded;
  private boolean partyLoaded;
  private boolean persoonLoaded;
  private boolean lidLoaded;
  
  private CSVWriter partyWriter;  
  private DatabaseManager db;

  public MainLogic()
  {
	  db = new DatabaseManager();
	  this.barcodeTable = new HashMap<String, String>();
	  this.partyTable = new ArrayList<String>();
	  this.peopleEntered = new ArrayList<String>();
	  preLoadTables();
	  this.ui = new UserInt(this);
	  try {
			ui.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
  }

  public void preLoadTables()
  {
    if (fileExists("savedTables/BarcodeTabel.csv"))
      try {
        File barcodeFile = new File("savedTables/BarcodeTabel.csv");
        loadBarcodeTable(barcodeFile);
      } catch (IOException localIOException) { }
    if (fileExists("savedTables/PersoonTabel.csv"))
      try {
        File persoonFile = new File("savedTables/PersoonTabel.csv");
        loadPersoonTable(persoonFile);
      } catch (IOException localIOException1) { }
    if (fileExists("savedTables/LidTabel.csv"))
      try {
        File lidFile = new File("savedTables/LidTabel.csv");
        loadLidTable(lidFile);
      } catch (IOException localIOException1) { }
  }

  public void loadBarcodeTable(File location) throws IOException{
    if (!fileExists(location)) {
      throw new IOException("Selected File does not exist");
    }
    CSVParser parser = new CSVParser(location);
    this.barcodeTable.clear();
    try {
		db.updateBarcodeTabel("savedTables/BarcodeTabel.csv");
	} catch (SQLException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
    if (!isValidBarcodeTable(parser))
      throw new IOException("Selected File was not a Barcode Table");
    do
    {
      String[] row = parser.getNext();
      this.barcodeTable.put(row[0], row[1]);
    }
    while (parser.hasNext());

    this.barcodeLoaded = true;
//    this.ui.showTableLoadingSucces("Barcode", location);
//    this.ui.completedStepOne();
  }

  public void loadPersoonTable(File location) throws IOException {
    if (!fileExists(location)) {
      throw new IOException("Selected File does not exist");
    }
    CSVParser parser = new CSVParser(location);

    if (!isValidPersoonTable(parser)) {
      throw new IOException("Selected File was not a Persoon Table");
    }
    this.persoonTable = parser.getCSVFile();

    this.persoonLoaded = true;
//    this.ui.showTableLoadingSucces("Persoon", location);
//    this.ui.completedStepTwo();
  }
  
  public void loadLidTable(File location) throws IOException {
	    if (!fileExists(location)) {
	      throw new IOException("Selected File does not exist");
	    }
	    CSVParser parser = new CSVParser(location);

	    if (!isValidLidTable(parser)) {
	      throw new IOException("Selected File was not a Lid Table");
	    }
	    this.lidTable = parser.getCSVFile();
	    
	    this.lidLoaded = true;
//	    this.ui.showTableLoadingSucces("Lid", location);
	  }
  
  public void updatePersoonTable() {
	try {
		db.updatePersonTabel("savedTables/PersoonTabel.csv");
//		ui.sfUpdate("Persoon");
	} catch (Exception e) { }
  }
  
  public void updateBarcodeTable() {
	 try {
		db.updateBarcodeTabel("savedTables/BarcodeTabel.csv");
//		ui.sfUpdate("Barcode");
	} catch (Exception e) {  }
  }
  
  public void updateLidTable() {
	try {
		db.updateLidTabel("savedTables/LidTabel.csv");
//		ui.sfUpdate("Lid");
	} catch (Exception e) {}
  }	

  public void loadPartyTable(File location) {
    try {
      CSVParser parser = new CSVParser(location);
      this.partyTable.clear();

      if (!isValidPartyTable(parser))
        throw new IOException("Selected File was not a Party Table");
      do
      {
        String[] row = parser.getNext();
        this.partyTable.add(row[0]);
        this.partyWriter = new CSVWriter(location, new String[] {"userid", "attended" });
        if ("true".equals(row[1])) {
        	this.peopleEntered.add(row[0]);
        	this.ui.addToAttendList(new String [] { getDisplayedName(row[0])});
        } 
        	
      }
      while (parser.hasNext());

      this.partyLoaded = true;
//      this.ui.showTableLoadingSucces("Party", location);
      String[] party = new String[this.partyTable.size()];
      this.partyTable.toArray(party);
//      this.ui.addToPartyList(getDisplayedName(party));
//      this.ui.completedStepThree();
    } catch (IOException e) {
    }
  }

  public void setPartySaveLocation(File location) {
	if (!location.getAbsolutePath().endsWith(".csv"))
		location = new File(location.getAbsolutePath() + ".csv");
    try {
      CSVWriter testWriter = new CSVWriter(location, new String[] { "userid", "attended"});
      this.partyWriter = testWriter;
      this.partyTable.clear();
    } catch (IOException e) {
      System.out.println(e.toString());
    }
    this.partyLoaded = true;
//    this.ui.completedStepThree();
  }

  public void verkoopKaart(String barcode) {
    String sNummer = getIdFromCode(barcode);
    if ((sNummer == null) || (this.partyWriter == null)) {
      return;
    }
    if (this.partyTable.contains(sNummer)) {
    	this.ui.displayText("De gebruiker heeft reeds een kaart gekocht");
      return;
    }
    this.partyTable.add(sNummer);
    String[] name = {getDisplayedName(sNummer)};
    this.ui.addToAttendList(name);
    this.ui.displayPositive();
    try {
      this.partyWriter.writeToFile(sNummer);
    } catch (IOException localIOException) {}
  }
  
  public void verkoopKaartSn(String sNummer) {
	    if (sNummer== null || (this.partyWriter == null)) {
	      return;
	    }
	    if (this.partyTable.contains(sNummer)) {
	      this.ui.displayText("Heeft al een kaart gekocht.");
	      return;
	    }
	    this.partyTable.add(sNummer);
	    String[] name = { getDisplayedName(sNummer)};
	    this.ui.addToAttendList(name);
	    this.ui.displayPositive();
	    try {
	    	this.partyWriter.writeToFile(sNummer);
	    } catch (IOException localIOException) {
	    }
  }

  public void attemptToEnter(String code) {
    String sNumber = getIdFromCode(code);
    if (sNumber != null)
    	attemptToEnterSn(sNumber); 	
  }
  
  public void attemptToEnterSn(String id) {
	  if ((this.partyTable.contains(id)) && (!this.peopleEntered.contains(id))) {
		  this.ui.removeFromAttendList(new String[] { getDisplayedName(id) });
		  this.ui.addToArrivedList(new String[] { getDisplayedName(id) });
		  this.ui.displayPositive();
		  this.peopleEntered.add(id);
		  this.partyTable.remove(id);
		  return;
	  } else if (this.peopleEntered.contains(id)) {
		  this.ui.displayText("Deze persoon is reeds aanwezig");
	  }
	  this.ui.displayNegative();
  }
  public void removeFromArrived(String id) {
	  peopleEntered.remove(id);
	  ui.addToAttendList(new String[] { getDisplayedName(id)});
	  ui.removeFromArrivedList(new String[] { getDisplayedName(id)});
  }
  
  public void removeFromAttended(String id) {
	  partyTable.remove(id);
	  ui.removeFromAttendList(new String[] { getDisplayedName(id)});
  }
  
  public boolean canSell() {
    return (this.barcodeLoaded) && (this.partyLoaded) && (this.persoonLoaded)
    			&& (this.lidLoaded);
  }

  private String getIdFromCode(String code) {
    return (String)this.barcodeTable.get(code);
  }
  
  private boolean isLid(String snummer) {
	  if (snummer == null)
		  return false;
	  
	  Iterator<String[]> it = lidTable.getRowIterator();
	  while (it.hasNext()) {
		  String[] cur = it.next();
		  if (cur[2].equals(snummer) && "1112".equals(cur[1]))
			  return true;
	  }
	  return false;  
  }

  private String getDisplayedName(String id) {
    String[] row = this.persoonTable.getFirst(0, id);
    String Lid = "NL";
    if (row != null) {
      if ("\\N".equals(row[1]))
        row[1] = "";
      if ("\\N".equals(row[2]))
        row[2] = "";
      
      if(isLid(id))
	    {
    	  Lid = "L";
	    }
      return id + " - " + row[1] + " " + row[2]+ " - " + Lid;
    }
    return id;
  }

  private String[] getDisplayedName(String[] ids) {
    String[] result = new String[ids.length];
    for (int i = 0; i < ids.length; i++) {
      result[i] = getDisplayedName(ids[i]);
    }
    return result;
  }
  
  private void closePartyTabel() throws IOException {
	  int amountOfMembers = partyTable.size();
	  for (int i = 0; i < amountOfMembers; i++) {
		  String[] input = new String[] { partyTable.get(i), "" + peopleEntered.contains(partyTable.get(i)) };
		  partyWriter.writeToFile(input);
	  }
	  partyWriter.close();
  }

  public void closeApp() {
    if (this.partyWriter == null)
      return;
    try {
      closePartyTabel();
    } catch (IOException localIOException) {
    }
    System.exit(0);
  }

  public static void main(String[] args) {
    new MainLogic();
  }

  private boolean fileExists(String url) {
    return new File(url).exists();
  }

  private boolean fileExists(File location) {
    return location.exists();
  }

  private boolean isValidBarcodeTable(CSVParser fileParser) {
    return (fileParser.getColumnNames().length == 2) && (fileParser.getColumnNames()[0].equals("code")) && (
      fileParser.getColumnNames()[1].equals("userid"));
  }

  private boolean isValidPersoonTable(CSVParser fileParser) {
    return (fileParser.getColumnNames().length == 9) && (fileParser.getColumnNames()[0].equals("userid")) && 
      (fileParser.getColumnNames()[1].equals("voornaam")) && (fileParser.getColumnNames()[2].equals("naam")) && 
      (fileParser.getColumnNames()[3].equals("stub")) && (fileParser.getColumnNames()[4].equals("creationtime")) && 
      (fileParser.getColumnNames()[5].equals("kaartnr")) && (fileParser.getColumnNames()[6].equals("irreeelbijcudi")) && 
      (fileParser.getColumnNames()[7].equals("wisselgegevensalumnivereniging")) && (
      fileParser.getColumnNames()[8].equals("kulinfoupdate"));
  }
  
  private boolean isValidLidTable(CSVParser fileParser) {
	    return (fileParser.getColumnNames().length == 4) && (fileParser.getColumnNames()[0].equals("id")) && 
	      (fileParser.getColumnNames()[1].equals("jaar")) && (fileParser.getColumnNames()[2].equals("persoon_userid")) && 
	      (fileParser.getColumnNames()[3].equals("type"));
	  }

  private boolean isValidPartyTable(CSVParser parser) {
    return (parser.getColumnNames().length == 2) && (parser.getColumnNames()[0].equals("userid")) &&
    		(parser.getColumnNames()[1].equals("attended"));
  }
}